package me.youline.dataServer.service.front;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import me.youline.dataServer.controller.dto.UserRelationStatusDTO;
import me.youline.dataServer.controller.dto.UserSocialRelFrontDTO;
import me.youline.dataServer.controller.dto.UserSocialRelationItemDTO;
import me.youline.dataServer.entity.MsgPraiseRecord;
import me.youline.dataServer.entity.UserSocialRelation;
import me.youline.dataServer.service.SocialRelationService;

import org.perf4j.aop.Profiled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 社交关系DTO与后端实体之间的映射器
 * 
 * @author linhan
 *
 */
@Component
public class SocialRelationDTOAdapter {

	@Autowired
	private SocialRelationService socialService;

	@Autowired
	private UserInfoDTOAdapter userInfoAssembler;

	/**
	 * 获取社交关系实体DTO基本方法
	 * 
	 * @param viewUserId
	 * @param inputs
	 * @param converter
	 * @return
	 */
	private <T> UserSocialRelFrontDTO getSocialRelDTO(Long viewUserId,
			List<T> inputs, Converter<T> converter) {
		UserSocialRelFrontDTO relDTO = new UserSocialRelFrontDTO();
		List<UserSocialRelationItemDTO> list = new ArrayList<UserSocialRelationItemDTO>();
		relDTO.setRelItems(list);
		relDTO.setTargetUserId(viewUserId);
		for (T r : inputs) {
			UserSocialRelationItemDTO itemDTO = converter
					.convert(viewUserId, r);
			if (itemDTO != null) {
				list.add(itemDTO);
			}
		}
		return relDTO;
	}

	/**
	 * 将点赞关系实体转换为社交关系实体
	 * 
	 * @param viewUserId
	 * @param input
	 * @return
	 */
	@Profiled(tag = "front-根据点赞记录获取关系展示实体")
	public UserSocialRelFrontDTO getSocialRelDTOForPraise(Long viewUserId,
			List<MsgPraiseRecord> input) {
		return this.getSocialRelDTO(viewUserId, input,
				this.new MsgPraiseRecorderConverter());
	}

	/**
	 * 根据用户id转换为用户社交关系DTO
	 * 
	 * @param viewUserId
	 * @param userIds
	 * @return
	 */
	@Profiled(tag = "front-根据用户id获取关系展示实体")
	public UserSocialRelFrontDTO getSocialRelDTOForUser(Long viewUserId,
			List<Long> userIds) {
		return this.getSocialRelDTO(viewUserId, userIds,
				this.new UserIdConverter());
	}

	/**
	 * 获取用户关注列表
	 * 
	 * @param viewUserId
	 * @param list
	 * @return
	 */
	public UserSocialRelFrontDTO getFollowingList(final Long viewUserId,
			Long targetUserId, List<UserSocialRelation> list) {
		return this.getSocialRelDTO(viewUserId, list,
				new UserSocialRelationListConverter(
						UserSocialRelationListConverter.FOLLOWING_List,
						viewUserId.equals(targetUserId)));
	}

	public UserRelationStatusDTO getRelationStatusDTO(Long targetUserId,
			Long currentUserId) {
		UserRelationStatusDTO dto = new UserRelationStatusDTO();
		dto.setCurrentUserId(currentUserId);
		dto.setTargetUserId(targetUserId);
		if (targetUserId.equals(currentUserId)) {
			dto.setIsFollowed(false);
			dto.setIsFollowing(false);
		} else {
			dto.setIsFollowed(socialService.isFollowed(currentUserId,
					targetUserId));
			dto.setIsFollowing(socialService.isFollowing(currentUserId,
					targetUserId));
		}
		return dto;
	}

	/**
	 * 获取用户粉丝列表
	 * 
	 * @param viewUserId
	 * @param list
	 * @return
	 */
	public UserSocialRelFrontDTO getFollowerList(final Long viewUserId,
			Long targetUserId, List<UserSocialRelation> list) {
		return this.getSocialRelDTO(viewUserId, list,
				new UserSocialRelationListConverter(
						UserSocialRelationListConverter.FOLLOWER_LIST,
						viewUserId.equals(targetUserId)));
	}

	/**
	 * 点赞用户列表关系转换器
	 * 
	 * @author linhan
	 *
	 */
	public class MsgPraiseRecorderConverter extends Converter<MsgPraiseRecord> {

		@Override
		public Long getUserId(MsgPraiseRecord t) {
			return t.getPraiseUserId();
		}

		@Override
		protected Long getSortId(MsgPraiseRecord t) {
			return t.getId();
		}

		@Override
		protected Date getCreateTime(MsgPraiseRecord t) {
			return t.getCreateTime();
		}

	}

	/**
	 * 用户社交关系列表转换器，他主要针对用户粉丝列表、与用户关注列表。 其存在如下需求： 1. 粉丝列表和关注列表存在排序的需求， 2.
	 * 列表用户的社交关系状态应该显示为与当前浏览的用户的关系，不是与粉丝列表或者关注列表拥有者。 3.
	 * 性能优化，即减少不必要的判断。当浏览者与拥有者是同一个人的时候，请求粉丝列表的时候就不要再判断，列表中用户是否关注拥有者
	 * 为此我们需要根据请求的是用户粉丝列表还是关注列表做区分，以获取正确的用户数据。并确定与浏览者社交关系
	 * 
	 * @author linhan
	 *
	 */
	public class UserSocialRelationListConverter extends
			Converter<UserSocialRelation> {

		/**
		 * 关注人列表
		 */
		public static final int FOLLOWING_List = 1;

		/**
		 * 粉丝列表
		 */
		public static final int FOLLOWER_LIST = 2;

		/**
		 * 列表类型标志
		 */
		private int flag;

		/**
		 * 浏览者与列表拥有者是否为同一人
		 */
		private boolean isSameUser;

		/**
		 * @param type
		 *            请求列表类型，粉丝列表 or 关注人列表
		 * @param isSameUser
		 *            浏览者和列表拥有者是否同属于一人
		 */
		public UserSocialRelationListConverter(int type, boolean isSameUser) {
			this.flag = type;
			this.isSameUser = isSameUser;
		}

		@Override
		public Long getUserId(UserSocialRelation t) {
			if (flag == FOLLOWER_LIST) {
				return t.getFromUserId();
			} else {
				return t.getToUserId();
			}
		}

		@Override
		protected Long getSortId(UserSocialRelation t) {
			return t.getId();
		}

		@Override
		protected Date getCreateTime(UserSocialRelation t) {
			return t.getCreateTime();
		}

		@Override
		protected boolean isFollowed(Long queryUserId, Long viewUserId) {
			if (isSameUser && this.flag == FOLLOWING_List) {
				return true;
			}
			return super.isFollowed(queryUserId, viewUserId);
		}

		@Override
		protected boolean isFollowing(Long queryUserId, Long viewUserId) {
			if (isSameUser && this.flag == FOLLOWER_LIST) {
				return true;
			}
			return super.isFollowing(queryUserId, viewUserId);
		}

	}

	public class UserIdConverter extends Converter<Long> {

		@Override
		public Long getUserId(Long t) {
			return t;
		}

		@Override
		protected Long getSortId(Long t) {
			return 0L;
		}

		@Override
		protected Date getCreateTime(Long t) {
			return null;
		}
	}

	private abstract class Converter<T> {

		public UserSocialRelationItemDTO convert(Long viewUserId, T t) {
			UserSocialRelationItemDTO itemDTO = new UserSocialRelationItemDTO();
			if (viewUserId.equals(this.getUserId(t))) {
				itemDTO.setIsFollowed(false);
				itemDTO.setIsFollowing(false);
			} else {
				itemDTO.setIsFollowed(this.isFollowed(this.getUserId(t),
						viewUserId));
				itemDTO.setIsFollowing(this.isFollowing(this.getUserId(t),
						viewUserId));
			}
			itemDTO.setUser(userInfoAssembler.getSimpleInfoDTO(this
					.getUserId(t)));
			itemDTO.setId(this.getSortId(t));
			itemDTO.setCreateTime(this.getCreateTime(t));
			return itemDTO;
		}

		/**
		 * 查询用户是否被浏览者关注
		 * 
		 * @param queryUserId
		 * @param viewUserId
		 * @return
		 */
		protected boolean isFollowed(Long queryUserId, Long viewUserId) {
			return socialService.isFollowed(queryUserId, viewUserId);
		}

		/**
		 * 查询用户是否关注浏览者
		 * 
		 * @param queryUserId
		 * @param viewUserId
		 * @return
		 */
		protected boolean isFollowing(Long queryUserId, Long viewUserId) {
			return socialService.isFollowing(queryUserId, viewUserId);
		}

		abstract public Long getUserId(T t);

		abstract protected Long getSortId(T t);

		abstract protected Date getCreateTime(T t);
	}

}
